/**
 * @filename:DocumentInfoServiceImpl 2025-04-27
 * @project starhub-schema  V1.0
 */
package com.starhub.engine.document.service.impl;

import com.starhub.api.document.service.HtmlToWordService;
import com.starhub.engine.directory.dao.DirectoryInfoDao;
import com.starhub.engine.directory.entity.DirectoryInfo;
import com.starhub.engine.document.dao.DocumentShareDao;
import com.starhub.engine.document.entity.DocumentShare;
import com.starhub.engine.document.request.DocumentInfoBsRequest;
import com.starhub.engine.document.result.DocumentDealListResult;
import com.starhub.engine.document.result.DocumentDealResult;
import com.starhub.engine.document.utils.DocConvertUtil;
import com.starhub.engine.document.utils.FileExtractor;
import com.starhub.engine.document.utils.FileType;
import com.starhub.engine.generator.genid.IdGenerator;
import com.starhub.engine.document.entity.DocumentInfo;
import com.starhub.engine.document.dao.DocumentInfoDao;
import com.starhub.engine.document.service.DocumentInfoService;
import com.starhub.common.exception.AppException;
import com.starhub.common.sys.user.LoginUser;
import com.starhub.utils.HtmlToDocxConverter;
import com.starhub.utils.Util;

import lombok.SneakyThrows;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

/**
 * @Description:(附件管理服务实现)
 *
 * @version: V1.0
 * @author: 孙赛赛-sss
 * 
 */
@Service
public class DocumentInfoServiceImpl implements DocumentInfoService {

    private static final Logger log = LoggerFactory.getLogger(DocumentInfoServiceImpl.class);
    @Autowired
    private DocumentInfoDao documentDao;

    @Autowired
    private DocumentShareDao documentShareDao;

    @Autowired
    private DirectoryInfoDao directoryInfoDao;

    /**
     * 新增
     * 
     * @param user
     * @param document
     * @return
     */
    @SneakyThrows
    public DocumentDealListResult addDocumentInfo(MultipartFile[] files, LoginUser user, DocumentInfo document){
        Long userId = Long.parseLong(user.getUserId());
        //判断用户是否有目录内文件创建权限
        List<DocumentShare> documentShares = documentShareDao.getDirectoryShareById(document.getDirectoryId(),userId);
        boolean permissionF = false;
        for(DocumentShare documentShare:documentShares){
            if(documentShare.getPermission()==6||documentShare.getPermission()==3){
                permissionF = true;
            }
        }
        if(!permissionF){//具有新建或者完全控制权限
            log.info("{}===当前登录用户没有文件新建权限",userId);
            return DocumentDealListResult.fail("当前登录用户没有文件新建权限");
        }
        //查询文档保存目录
        DirectoryInfo directory = directoryInfoDao.selectByPrimaryKey(document.getDirectoryId());
        //设置文档保存根路径
        Path root = Paths.get(directory.getDirectoryPath());
        //查询所有具有目录权限的用户
        IdGenerator idGenerator = new IdGenerator(1,1);
        List<DocumentInfo> documentInfos = new ArrayList<>();
        for(MultipartFile file:files){
            String fileName = file.getOriginalFilename();
            String uid = Util.null2String(document.getUid());
            Long fileId = idGenerator.generate();
            uid = Util.isEmpty(uid) ? Util.null2String(fileId) : uid;

            String ext = "";
            if (fileName != null && fileName.contains(".")) {
                ext = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
            }
            Path filepath = root.resolve(uid+ext);
            Files.copy(file.getInputStream(), filepath, StandardCopyOption.REPLACE_EXISTING);

            //保存附件到数据库表
            DocumentInfo fileSystem = new DocumentInfo();
            fileSystem.setId(fileId);
            if("".equals(document.getFileName())){
                fileSystem.setFileName(file.getOriginalFilename());
            }else{
                fileSystem.setFileName(document.getFileName());
            }
            fileSystem.setExt(ext);
            fileSystem.setUid(uid);
            fileSystem.setFilePath(filepath.toString());
            fileSystem.setDirectoryId(document.getDirectoryId());
            fileSystem.setUserId(userId);
            fileSystem.setUploadDateTime(new Date());
            int size = documentDao.insert(fileSystem);
            log.info("{} 文件新建===结果=={}",fileId,size);
            if(size>0){
                documentInfos.add(fileSystem);
                //优先插入创建人的完全控制权限
                DocumentShare documentShare1 = new DocumentShare();
                documentShare1.setId(idGenerator.generate());
                documentShare1.setUserId(userId);
                documentShare1.setPermission(3);
                documentShare1.setFileId(fileId);
                documentShare1.setCreateDateTime(new Date());
                documentShareDao.insert(documentShare1);
                //进行文件的赋权
                ExecutorService executor = Executors.newSingleThreadExecutor();
                executor.execute(()->{
                    //查询所有具有目录权限的用户
                    List<DocumentShare> fileSystemShares = documentShareDao.getDirectoriesById(document.getDirectoryId());
                    for(DocumentShare tempShare:fileSystemShares){
                        //这里权限转换有问题 暂时不调整
                        //0新建 1查看 2下载 3完全控制 4删除 5编辑 6目录下文件新建权限 7目录下文件编辑权限 8目录下文件查看 9目录下文件下载 10目录下文件删除
                        Integer permission = -1;
                        if(tempShare.getPermission()==6){
                            permission = 0;
                        }else if(tempShare.getPermission()==7){
                            permission = 5;
                        }else if(tempShare.getPermission()==8){
                            permission = 1;
                        }else if(tempShare.getPermission()==9){
                            permission = 2;
                        }else if(tempShare.getPermission()==10){
                            permission = 4;
                        }
                        if(permission==-1)continue;
                        Long shareId = idGenerator.generate();
                        DocumentShare Share = new DocumentShare();
                        Share.setId(shareId);
                        Share.setUserId(tempShare.getUserId());
                        Share.setPermission(permission);
                        Share.setFileId(fileId);
                        Share.setCreateDateTime(new Date());
                        int shareAdd = documentShareDao.insert(Share);
                        log.info("{} 文件进行赋权===结果=={}",fileId,shareAdd);
                    }
                    executor.shutdown();
                });
            }
        }
        return DocumentDealListResult.success(documentInfos,documentInfos.size());
    }

    @SneakyThrows
    @Override
    public Map<String, Object> downloadFile(Long fileId, LoginUser user) {
        Long userId = Long.parseLong(user.getUserId());
        Map<String,Object> result = new HashMap<>();
        //判断用户是否有目录内文件创建权限
        List<DocumentShare> documentShares = documentShareDao.getDocumentShareById(fileId,userId);
        boolean permissionF = false;
        for(DocumentShare documentShare:documentShares){
            if(documentShare.getPermission()==2||documentShare.getPermission()==3){
                permissionF = true;
            }
        }
        permissionF = true;
        //0新建 1查看 2下载 3完全控制 4删除 5编辑 6目录下文件新建权限 7目录下文件编辑权限 8目录下文件查看 9目录下文件下载 10目录下文件删除
        if(!permissionF){//具有新建或者完全控制权限
            result.put("status",false);
            result.put("msg","当前登录用户没有文件下载权限");
            return result;
        }
        DocumentInfo fileSystem = documentDao.selectByPrimaryKey(fileId);
        if(fileSystem !=null){
            String filePath = fileSystem.getFilePath();
            String fileName = fileSystem.getFileName();
            result.put("filePath",filePath);
            result.put("fileName",fileName);
            result.put("status",true);
        }else{
            result.put("status",false);
        }
        return result;
    }

    /**
    * 更新
    * @param user
    * @param document
    * @return
    */
    public DocumentDealResult updateDocumentInfo(LoginUser user, DocumentInfo document){
        //需要先判断有没有编辑权限
        Long userId = Long.parseLong(user.getUserId());
        //判断用户是否有文件夹的创建权限
        List<DocumentShare> documentShares = documentShareDao.getDirectoryShareById(document.getDirectoryId(),userId);
        boolean permissionF = false;
        for(DocumentShare documentShare:documentShares){
            if(documentShare.getPermission()==5||documentShare.getPermission()==3){
                permissionF = true;
            }
        }
        if(!permissionF){//具有新建或者完全控制权限
            log.info("{}===当前登录用户没有编辑权限",userId);
            return DocumentDealResult.fail("当前登录用户没有编辑权限");
        }
        //不允许更新的属性设置为null
        document.setUploadDateTime(null);
        document.setUserId(null);
        document.setDirectoryId(null);
        document.setFilePath(null);
        int edit = documentDao.updateByPrimaryKeySelective(document);
        log.info("更新结果==={}",edit>0?"目录编辑成功":"目录编辑失败");
        return DocumentDealResult.success(String.valueOf(document.getId()),document);
    }

    /**
    * 基本信息获取
    * @param user
    * @param id
    * @return
    */
    public DocumentDealResult getDocumentInfoInfo(LoginUser user, Long id){
        Long userId = Long.parseLong(user.getUserId());
        //判断用户是否有文件的查看权限
        List<DocumentShare> documentShares = documentShareDao.getDocumentShareById(id,userId);
        boolean permissionF = false;
        for(DocumentShare documentShare:documentShares){
            if(documentShare.getPermission()==1||documentShare.getPermission()==3){
                permissionF = true;
            }
        }
        //0新建 1查看 2下载 3完全控制 4删除 5编辑 6目录下文件新建权限 7目录下文件编辑权限 8目录下文件查看 9目录下文件下载 10目录下文件删除
        if(!permissionF){//具有新建或者完全控制权限
            log.info("{}===当前登录用户没有文件查看权限",userId);
            return DocumentDealResult.fail("当前登录用户没有文件查看权限");
        }
        return DocumentDealResult.success(String.valueOf(id),documentDao.selectByPrimaryKey(id));
    }

    @SneakyThrows
    @Override
    public DocumentDealResult getContentByFileId(LoginUser user, Long id) {
        Long userId = Long.parseLong(user.getUserId());
        //判断用户是否有文件的查看权限
        List<DocumentShare> documentShares = documentShareDao.getDocumentShareById(id,userId);
        boolean permissionF = false;
        for(DocumentShare documentShare:documentShares){
            if(documentShare.getPermission()==0||documentShare.getPermission()==1||documentShare.getPermission()==2||documentShare.getPermission()==3||documentShare.getPermission()==4||documentShare.getPermission()==5){
                permissionF = true;
            }
        }
        if(!permissionF){//没有文件的任何权限
            log.info("{}===当前登录用户没有文件权限",userId);
            return DocumentDealResult.fail("当前登录用户没有文件权限");
        }
        DocumentInfo document = documentDao.selectByPrimaryKey(id);
        String filePath = document.getFilePath();
        InputStream inputStream = new FileInputStream(filePath);
        FileType fileType = FileType.fromFileName(filePath);
        return DocumentDealResult.success(String.valueOf(id),FileExtractor.extractText(inputStream,fileType, StandardCharsets.UTF_8));
    }

    @SneakyThrows
    @Override
    public DocumentDealResult getHtmlByFileId(LoginUser user, Long id) {
        Long userId = Long.parseLong(user.getUserId());
        //判断用户是否有文件的查看权限
        List<DocumentShare> documentShares = documentShareDao.getDocumentShareById(id,userId);
        boolean permissionF = false;
        for(DocumentShare documentShare:documentShares){
            if(documentShare.getPermission()==0||documentShare.getPermission()==1||documentShare.getPermission()==2||documentShare.getPermission()==3||documentShare.getPermission()==4||documentShare.getPermission()==5){
                permissionF = true;
            }
        }
        if(!permissionF){//没有文件的任何权限
            log.info("{}===当前登录用户没有文件权限",userId);
            return DocumentDealResult.fail("当前登录用户没有文件权限");
        }

        DocumentInfo document = documentDao.selectByPrimaryKey(id);
        String filePath = document.getFilePath();
        InputStream inputStream = new FileInputStream(filePath);
        FileType fileType = FileType.fromFileName(filePath);
        return DocumentDealResult.success(String.valueOf(id),DocConvertUtil.extractHtml(inputStream,fileType, StandardCharsets.UTF_8));
    }
    
    @SneakyThrows
    @Override
    public DocumentDealResult convertHtml2Word(LoginUser user,DocumentInfoBsRequest documentInfoBsRequest) {
        //查询文档保存目录
        DirectoryInfo directory = directoryInfoDao.selectByPrimaryKey(documentInfoBsRequest.getDirectoryId());
        //设置文档保存根路径
        Path root = Paths.get(directory.getDirectoryPath());
        IdGenerator  idGenerator = new IdGenerator(1,1);
        String fileName = documentInfoBsRequest.getFileName();
        Long uid = idGenerator.generate();
        Path filepath = root.resolve( uid + fileName);
        XWPFDocument document = HtmlToWordService.htmlConvertWord(documentInfoBsRequest.getHtml());
        document.write(new FileOutputStream(filepath.toString()));
        String ext = "";
        if (fileName != null && fileName.contains(".")) {
            ext = fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
        }
        Long fileId = idGenerator.generate();
        DocumentInfo fileSystem = new DocumentInfo();
        fileSystem.setId(fileId);
        fileSystem.setExt(ext);
        fileSystem.setFileName(fileName);
        fileSystem.setUid(String.valueOf(uid));
        fileSystem.setFilePath(filepath.toString());
        fileSystem.setDirectoryId(documentInfoBsRequest.getDirectoryId());
        fileSystem.setUserId(Long.parseLong(user.getUserId()));
        fileSystem.setUploadDateTime(new Date());
        int size = documentDao.insert(fileSystem);
        if(size>0){
            //优先插入创建人的完全控制权限
            DocumentShare documentShare1 = new DocumentShare();
            documentShare1.setId(idGenerator.generate());
            documentShare1.setUserId(Long.parseLong(user.getUserId()));
            documentShare1.setPermission(3);
            documentShare1.setFileId(fileId);
            documentShare1.setCreateDateTime(new Date());
            documentShareDao.insert(documentShare1);
        }
        return DocumentDealResult.success(String.valueOf(fileId),fileSystem);
    }

    /**
    * 根据id删除，此方法为真实删除
    * @param user
    * @param ids
    */
    public DocumentDealResult deleteDocumentInfoRecord(LoginUser user, String ids){
        Long userId = Long.parseLong(user.getUserId());
        //数组转换
        List<Long> idList = Arrays.stream(ids.split(","))
                .map((id) -> Long.parseLong(id))
                .collect(Collectors.toList());
        List<DocumentShare> documentShares = documentShareDao.getDocumentSharesById(idList,userId);
        List<Long> permissionLits = new ArrayList<>();
        for(DocumentShare documentShare:documentShares){
            if(documentShare.getPermission()==3||documentShare.getPermission()==4){//完全控制或者删除权限
                permissionLits.add(documentShare.getFileId());
            }
        }
        if(permissionLits.size()<documentShares.size()){
            return DocumentDealResult.fail("部分文件无删除权限，无法删除");
        }
        if(!permissionLits.isEmpty()){
            //删除附件
            documentDao.deleteDocumentInfoRecord(permissionLits);
            //删除共享表
            documentShareDao.deleteDocumentShareByFileId(permissionLits);
        }
        return DocumentDealResult.success(ids,"删除成功");
    }

    /**
    * 列表查询
    * @param user
    * @param params
    */
    public DocumentDealListResult getDocumentInfoList(LoginUser user, Map<String , Object>  params){
        Long userId = Long.parseLong(user.getUserId());
        List<DocumentInfo> documentInfos = documentDao.selectByParams(params,userId);
        return DocumentDealListResult.success(documentInfos,documentInfos.size());
    }

    @Override
    public DocumentDealListResult getDocumentListByDir(DocumentInfoBsRequest documentInfoBsRequest) {
        Integer pageNo = documentInfoBsRequest.getPageNo();
        Integer pageSize = documentInfoBsRequest.getPageSize();
        Long directoryId = documentInfoBsRequest.getDirectoryId();
        Integer newPageNo = (pageNo-1) * pageSize;
        List<DocumentInfo> documentInfos = documentDao.getDocumentListByDir(directoryId,newPageNo,pageSize);
        return DocumentDealListResult.success(documentInfos,documentInfos.size());
    }

    @Override
    public DocumentDealResult convertHtmlToDocxAdvanced(LoginUser user, DocumentInfoBsRequest request) {
        try {
            // 1. 查询文档保存目录
            DirectoryInfo directory = directoryInfoDao.selectByPrimaryKey(request.getDirectoryId());
            // 2. 设置文档保存根路径
            Path root = Paths.get(directory.getDirectoryPath());
            // 3. 生成唯一文件名
            IdGenerator idGenerator = new IdGenerator(1, 1);
            String fileName = request.getFileName();
            Long uid = idGenerator.generate();
            Path filepath = root.resolve(uid + ".docx");
            // 4. 使用新的转换器进行转换
            XWPFDocument document = HtmlToDocxConverter.convertHtmlToDocx(request.getHtml());
            // 5. 保存文档
            try (FileOutputStream out = new FileOutputStream(filepath.toString())) {
                document.write(out);
            }
            // 6. 保存文档信息
            DocumentInfo fileSystem = new DocumentInfo();
            fileSystem.setId(uid);
            fileSystem.setFileName(fileName);
            fileSystem.setFilePath(filepath.toString());
            fileSystem.setExt(".docx"); // Set the file extension
            fileSystem.setUid(uid.toString()); // Set the unique identifier
            fileSystem.setDirectoryId(request.getDirectoryId());
            fileSystem.setUserId(Long.parseLong(user.getUserId()));
            fileSystem.setUploadDateTime(new Date());

            int size = documentDao.insert(fileSystem);
            if (size > 0) {
                // 7. 设置文档权限
                DocumentShare documentShare = new DocumentShare();
                documentShare.setId(idGenerator.generate());
                documentShare.setFileId(uid);
                documentShare.setUserId(Long.parseLong(user.getUserId()));
                documentShare.setPermission(3); // 完全控制权限
                documentShare.setCreateDateTime(new Date());
                documentShareDao.insert(documentShare);

                return DocumentDealResult.success(String.valueOf(uid),fileSystem);
            }
            return DocumentDealResult.fail("文档保存失败");
        } catch (Exception e) {
            log.error("HTML转DOCX失败", e);
            throw new AppException("HTML转DOCX失败: " + e.getMessage());
        }
    }

}